home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Trading on the Edge
/
Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin
/
pc
/
mac_file
/
vendor_d
/
neuralwa
/
nw2v50
/
n2rand.c
< prev
next >
Wrap
Text File
|
1993-08-23
|
12KB
|
347 lines
/* $Id$ */
/* $Log$ */
/* n2rand.c - NeuralWare Standard Random Number Generator */
/* Version 1.1 of 6 March 1990 */
/************************************************************************
* Copyright(C) 1987-1992 NeuralWare Inc *
* Penn Center West, IV-227, Pittsburgh, PA 15276 *
* Telephone: (412) 787-8222 FAX: (412) 787-8220 *
* *
* All rights reserved. No part of this program may be reproduced, *
* stored in a retrieval system, or transmitted, in any form or by any *
* means, electronic, mechanical, photocopying, recording or otherwise *
* without the prior written permission of the copyright owner, *
* NeuralWare, Inc. *
* *
* PROPRIETARY NOTICE *
* *
* This document is the property of NeuralWare, Inc. and contains *
* trade-secrets and other proprietary information. The information *
* herein is reserved as proprietary to NeuralWare, and is not to be *
* published, reproduced, copied, disclosed, used, or reverse *
* engineered without the express written consent of a duly authorized *
* representative of NeuralWare. *
************************************************************************
*/
/************************************************************************
* *
* Random Number Generator for NeuralWare Products *
* *
************************************************************************
05-Dec-90 cck
Modified n2rand.c and n2rand.h for stand-alone operation and
easy integration with flash code.
Moved RRand() and GRand() from n2fl_sum.c to n2rand.c
*/
/* Its purpose is to provide a standard random number generator across all */
/* products that NeuralWare sells and supports. */
/* This code derived from Knuth, The Art of Computer Programming, Vol2, */
/* Seminumerical Algorithms; Sedgewick, Algorithms; and Press, Flannery, */
/* Teukolsky, and Vetterling, Numerical Recipes in C */
/* The concept is to use one type of generator, a linear congruential */
/* generator, to fill an array with random numbers. We then shuffle that */
/* array, and then take the difference between two of those random numbers */
/* in the array. That value is returned to the user, and also used to */
/* replace one of the numbers in the random number array. */
/* NRAND Returns a uniform random deviate between 0 and MAXRAND-1. */
/* Call NRAND as so: (SL) new_deviate = nrand(); */
/* SRAND Sets seed of random sequence to another part of the sequence. */
/* Call SRAND as so: SRAND( (SL) mi_random_seed ); */
#include <math.h>
#include "n2rand.h" /* defines MAXRAND & others */
static long rand_array[56]; /* Lookup table of random numbers */
static long first_gen, second_gen; /* Result for the LCG */
static int table_index, loop; /* Index into random number table */
static int first_time_flag = 1; /* First time thru flag -
initially true */
static int cursor_1, cursor_2, i; /* Cursors to chose random #'s from
lookup table of random #'s */
/* */
/************************************************************************
* *
* set_rand() - Random number seed *
* *
************************************************************************
*/
#ifdef PROTOTYPING
void set_rand( long seed )
#else
void set_rand( seed )
long seed;
#endif
{
/* Reset first_time_flag on the first call */
if ( first_time_flag ) {
/* Now reset first time flag */
first_time_flag = 0; /* now false */
}
/* Now test & correct seed value */
first_gen = MSEED - (seed < 0 ? -seed : seed);
first_gen %= MAXRAND;
rand_array[55] = first_gen;
second_gen = 1;
/* Now initialize the shuffle table */
/* We use a linear congruential generator to set up initial table */
for ( table_index = 1; table_index <= 54; table_index++)
{
i = (21*table_index) % 55;
rand_array[i] = second_gen;
second_gen = first_gen - second_gen;
if ( second_gen < MZ ) second_gen += MAXRAND;
first_gen = rand_array[i];
} /* End of for table_index = 1 to 54 */
/* Now randomize the table */
for (loop=1; loop<=4; loop++)
{
for ( table_index=1; table_index <= 55; table_index++)
{
rand_array[table_index] -= rand_array[1 +
(table_index+30) % 55];
if ( rand_array[table_index] < MZ ) rand_array[table_index]
+= MAXRAND;
}
}
/* Finish up any remaining bits */
cursor_1 = 0; /* init cursors into random # table */
cursor_2 = 31;
} /* End of initialization/setup code (if first_time true or reinit) */
/* */
/************************************************************************
* *
* nrand() - NeuralWare Random Number Generator *
* *
************************************************************************
*/
long nrand()
{
/* Retrieve random number & generate a new replacement value */
/* Initialize on the first call, if not already initialized by set_rand */
if ( first_time_flag ) {
set_rand(0);
/* Now reset first time flag */
first_time_flag = 0; /* now false */
}
if (++cursor_1 == 56) cursor_1 = 1; /* rollover so 1 to 55 */
if (++cursor_2 == 56) cursor_2 = 1; /* rollover so 1 to 55 */
/* now get diff of 2 random #'s */
first_gen = rand_array[cursor_1]-rand_array[cursor_2];
/* correct for rollover */
if ( first_gen < MZ ) first_gen += MAXRAND;
/* replace old random # */
rand_array[cursor_1] = first_gen;
/* and return random # to user */
return first_gen;
}
/* */
/************************************************************************
* *
* RRand(), GRand() - real random number generators *
* *
* RRand - Uniform Distribution *
* GRand - Gaussian Distribution *
* *
************************************************************************
*/
double RRand( lv, hv )
double lv, hv; /* low / high limits */
{
double rv; /* return value */
rv = nrand() * RANDINV; /* rand() / whatever value is needed */
rv = (hv - lv) * rv + lv; /* range adjusted */
return( rv );
}
double GRand( lv, hv )
double lv, hv; /* low / high limits */
{
static int k=0; /* k=0 need to caluclate g0 & g1,
* k=1 g1 already calculated */
static double g0,g1; /* Gaussian(0,1) random variables */
double u0,u1; /* uniforms on -1 to 1 */
double r2; /* radius from (0,0) to (u0,u1) */
double x,y; /* intermediate calculations */
if( k ) {
k = 0;
return( 0.5 * (hv - lv) * g1 + 0.5 * (hv + lv) );
} else {
k = 1;
/* find two U(-1,1)'s that are independent and lie within unit circle
* using NeuralWare's stanard uniform generator
*/
u1 = 2.0 * (nrand() * RANDINV) - 1.0;
y = u1 * u1;
for(r2=2.0; r2>1.0; ) {
u0 = u1;
r2 = y;
u1 = 2.0 * (nrand() * RANDINV) - 1.0;
y = u1 * u1;
r2 += y;
}
/* now get two Gaussian(0,1) */
x = sqrt( ( -2.0 * log(r2) )/ r2 );
g0 = u0 * x;
g1 = u1 * x;
return( 0.5 * (hv - lv) * g0 + 0.5 * (hv + lv) );
}
}
/* */
#ifdef TEST_RAN
/************************************************************************
*
* Test Routine for Random Number Generator
*
************************************************************************
*/
/* The following code is a simple test harness for the random number */
/* generator. This was derived from Sedgewick, Algorithms, Addison-Wesley, */
/* 1984. */
#include "usermath.h"
#define R_MAX 2000 /* This implies up to 2000 values in histogram */
SREAL chi_square( N, r )
UL N, r;
/*
This routine calculates the sum of the squares of the frequencies
of occurence of each random index produced via nrand. The sum is
then scaled by the expected frequency of occurence, and normalized
by the size of the sequence.
*/
/*
N is the total number of random numbers we wish to generate
r is the range we wish to produce random number in; The numbers
generated range from 0 thru r-1.
A good fit is indicated by how close this 'Chi-Square' is to the
expected value, i.e. for 10000 random numbers ranging between 1 &
100, a 'good' Chi-square would be around 100 in value
*/
{
static long f[R_MAX];
static long i, index;
static SREAL temp, t1, t2;
/* First clear out the histogram array */
for (index=0; index<R_MAX; index++) f[index] = 0;
/* Now accumulate a histogram of times a given index is produced */
for (i=0; i<N; i++) {
#if 1 /* set this 1 to test Neuralware generator */
t1 = nrand();
t2 = r;
index = (t1*t2)*RANDINV;
#endif
#if 0 /* set this 1 to test alternate generator */
t1 = random();
t2 = r;
index = (t1*t2)/2147483647.0;
#endif
if ( index >= R_MAX || index < 0 ) {
printf("ERROR - Chi-square, index = %d\n",i);
index = 0;
};
f[index] = f[index] + 1;
}
/* Now calculate the Chi Square of those frequencies */
/* We use floating point calculations to see any patterns in low order bits */
t1 = 0.0;
t2 = r;
for (i=0; i<=r-1 ; i++)
t1 = t1 + (f[i]-(N/r))*(f[i]-(N/r));
temp = ((t2*t1)/N);
return temp;
}
#ifdef __ZTC__ /* if Zortech C */
#include <time.h>
#endif
main()
#define SAMPLE_SIZE 1000
#define RANGE 100
#define NTRIALS 10
{
NINT i; /* loop index */
SREAL temp[NTRIALS]; /* temporary store */
SL seed; /* seed for random number generator */
#ifdef __ZTC__ /* if Zortech C */
time_t start, finish; /* data structures to measure run time of rand funct */
#endif
/* First reseed random number generator */
seed = 0;
set_rand(seed);
/* Second, start the loop for Ntrials of random numbers */
#ifdef __ZTC__ /* if Zortech C */
time (&start);
for (i=0; i< NTRIALS; i++) {
temp[i] = chi_square(SAMPLE_SIZE, RANGE);
}
time(&finish);
#else
for (i=0; i< NTRIALS; i++) {
temp[i] = chi_square(SAMPLE_SIZE, RANGE);
}
#endif
/* Third, print out the duration per call & CHI square values */
#ifdef __ZTC__ /* if Zortech C */
printf("time per Random call %2.10f seconds\n",
(difftime(finish, start)/SAMPLE_SIZE));
#endif
for (i=0; i< NTRIALS; i++)
printf("Trial # %d CHI Square = %f\n",i,temp[i]);
}
#endif /* ifdef TEST_RAN */